/*
  File:    band.h
  Purpose: Define a band matrix class that's useful for 
           solving large linear systems. Much better 
		  memory use.

  Contact: Paul Macklin
           pmacklin@math.uci.edu
		  http://math.uci.edu/~pmacklin
*/

Matrix Perturb( Matrix &In, double Size );
void swap(double *dIn1, double *dIn2);

#ifndef __band__
#define __band__

class BandMatrix
{
 public:
  Matrix Mat;
  int nLowerBandwidth;
  int nUpperBandwidth;
  int Rows; 
  int Cols;
  
  int TellRows( void );
  int TellCols( void );
  
  /*
    New additions for more efficient multiplications
  */
  Matrix NonzeroBandsBinary;
  Matrix NonzeroBandsList;
  int nNumberOfNonzeroBands;
  /*
    New addition for compactification
  */
  bool bIsCompacted;
    
  BandMatrix();
  BandMatrix(int nR, int nC, int nLBW, int nUBW);
  BandMatrix(int nR, int nC, int nLBW, int nUBW, Matrix& NzBLt);
  double* e(int nI, int nJ);
  double* eNoUpdate(int nI, int nJ);
  
  void UpdateNonzeroBandsList(void);
  void CleanupBandMatrix(void);
  void bandec( BandMatrix *bmL, int nIndex[] , double *dOut);
  void banbks( BandMatrix *bmL, int nIndex[] , Matrix *mRHS);

  void bandlinsolve( Matrix *mRHS);
  void bandBiCGsolve(BandMatrix *bmTranspose, Matrix *vRHS, 
                               Matrix *vInitialGuess, double dTolerance, 
                               int nMaxIterations);
                               
  double bandlinsolveBiCGStabOf2( Matrix *vRHS, Matrix *vInitialGuess , 
                                double dTolerance , int nMaxIterations );                                                               
                                
  double bandlinsolveBiCGStabOfL( Matrix *vRHS, Matrix *vInitialGuess , int L,
                                  double dTolerance , int nMaxIterations );
                                
  void ThomasSolve( Matrix* vRHS, Matrix *vSolution );      
                               
  void Compactify(void); // takes an existing band matrix, makes compact
  void Decompactify(void); // undoes the above
  void CreateCompact(Matrix& mInput); // takes uninitialized matrix 
                                      // and puts it into immediate compact form
  // note: I'll need to update the .e operations, too.
  
  /*
    Efficient multiplication of M*mIn
  */
  
  Matrix BandMultiplyCompacted(Matrix *mIn); 
  Matrix BandMultiplyUncompacted(Matrix *mIn); 
  Matrix BandMultiply(Matrix *mIn);
  
  void bandlinsolveBiCG( Matrix *mRHS, Matrix *vInit);
  void display(void);
};

#endif

BandMatrix transpose(BandMatrix &mIn);
Matrix CreateInitialGuess( Matrix *mIn);
